package com.aiti.lulian.gxmh.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.aiti.base.core.base.service.iml.BaseSerivceImpl;
import com.aiti.base.core.exception.BusinessException;
import com.aiti.base.core.page.PageInfo;
import com.aiti.base.core.page.PageResult;
import com.aiti.base.core.utils.uuid.UUIDUtil;
import com.aiti.lulian.constant.GxmhConstant;
import com.aiti.lulian.gxmh.dto.GovArticleBodyAndFileDto;
import com.aiti.lulian.gxmh.dto.GxmhPolicyParamDto;
import com.aiti.lulian.gxmh.dto.SysUserDto;
import com.aiti.lulian.gxmh.entity.GovArticle;
import com.aiti.lulian.gxmh.vo.GxmhPolicyCountVo;
import com.aiti.lulian.gxmh.vo.GxmhPolicyVo;
import com.aiti.lulian.mapper.gxmh.GovArticleMapper;
import com.aiti.lulian.gxmh.service.GovArticleService;
import com.aiti.lulian.gxmh.util.JsoupUtils;
import com.aiti.lulian.mapper.gxmh.GxmhSysMapper;
import com.aiti.lulian.utils.BusinessUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * description:
 * auth fcb
 * date 2025-06-09 14:23
 **/
@Service
@Slf4j
public class GovArticleServiceImpl extends BaseSerivceImpl<GovArticleMapper, GovArticle> implements GovArticleService {

    // 工业和信息化厅
    private static final String GOV_LIST_URL = "http://gxt.shandong.gov.cn/col/%s/index.html?number=%s&uid=%s&pageNum=%s";
    private static final String GOV_FILE_PATH = "/home/wechat_pc/zc_html";

    private static final String GOV_FILE_ATTACHMENT_PATH = "/home/wechat_pc/zc_html/attachment/";

    // 政策类型对应的字典表id
    private static final Map<String, String> policyTypeMap = new HashMap<>();

    static {
        policyTypeMap.put("规范性文件", "bd20c662de6611ec848100163e06b123");
        policyTypeMap.put("其他文件", "bd20c662de6611ec848100163e06b123");
        policyTypeMap.put("规范性文件清理", "bd20c662de6611ec848100163e06b123");
        policyTypeMap.put("政策解读", "bd20c662de6611ec848100163e06b456");
    }

    @Autowired
    private GxmhSysMapper gxmhSysMapper;

    @Override
    public GxmhPolicyVo getArticle(String uuid) {
        if(StrUtil.isEmpty(uuid)) {
            throw new BusinessException("参数错误");
        }
        GxmhPolicyVo policyDetail = this.baseMapper.getPolicyDetail(uuid);
        this.baseMapper.updateClickCount(uuid);
        return policyDetail;
    }

    @Override
    public GxmhPolicyVo getHotArticle(String province,String city, String county) {

        GxmhPolicyVo hotArticle = this.baseMapper.getHotPolicy(province, city, county);
        return hotArticle;
    }

    /**
     * 查询不同层级政策数量
     * @return
     */
    @Override
    public List<GxmhPolicyCountVo> queryPolicyCountList() {
        Integer guo = this.baseMapper.queryCountByLevel("国");
        Integer prov = this.baseMapper.queryCountByLevel("省");
        Integer city = this.baseMapper.queryCountByLevel("市");
        List<GxmhPolicyCountVo> result = new ArrayList<>();
        result.add(new GxmhPolicyCountVo("国", guo));
        result.add(new GxmhPolicyCountVo("省", prov));
        result.add(new GxmhPolicyCountVo("市", city));
        return result;
    }

    /**
     * 查询政策列表
     * @param queryDto
     * @return
     */
    public PageResult<GxmhPolicyVo> queryPolicyList(GxmhPolicyParamDto queryDto) {
        BusinessUtil.checkPageParam(queryDto);

        if(StrUtil.isEmpty(queryDto.getPublishTimeSort())) {
            queryDto.setPublishTimeSort("desc");
        }
        IPage<GxmhPolicyVo> page = new Page<>(queryDto.getPageNum(), queryDto.getPageSize());
        List<GxmhPolicyVo> list = this.baseMapper.queryPolicyList(page, queryDto);
        PageResult<GxmhPolicyVo> pageResult = new PageResult<>(list, new PageInfo(queryDto.getPageNum(), queryDto.getPageSize()), page.getTotal());
        return pageResult;
    }

    /**
     * 抓取政策文件列表。
     * 先根据类型获取文件列表，再逐个获取文章。将文章保存为html文件，只有文章保存成功才会将记录插入数据库
     * 注意：
     *      可能某些情况下分页参数不起作用，原网站是在前端返回所有数据，在前端分页
     * @param type 文件类型 见 http://gxt.shandong.gov.cn/col/col103862/index.html?number=SD020203
     * @param pageNum 分页
     */
    @Override
    public void requestListPage(String type, String pageNum) {
        String govListUrl = this.getGovListUrl(type, pageNum);
        Document documentFromURL = JsoupUtils.getDocumentFromURL(govListUrl);
        if(documentFromURL == null) {
            throw new BusinessException("请求"+type+"政策文件列表页失败");
        }
        Element div641892 = documentFromURL.getElementById("641892");
        if(div641892 == null) {
            throw new BusinessException("无法解析政策列表页面的文章列表");
        }
        Element child_1 = div641892.child(0);
        if(child_1 == null) {
            throw new BusinessException("无法解析政策列表页面的文章列表");
        }
        Document parse = Jsoup.parse(child_1.html());
        Elements recordList = parse.getElementsByTag("record");
        if(CollectionUtil.isEmpty(recordList)) {
            log.info("没有获取到政策列表页文章列表record数据");
            return;
        }
        for(Element record : recordList) {
            try {
                String html = record.html().replace("]]>", "").replace("<![CDATA[", "");
                Document recordDocument = Jsoup.parse(html);
                Elements liList = recordDocument.getElementsByTag("li");
                if (CollectionUtil.isEmpty(liList)) {
                    continue;
                }
                Element li = liList.get(0);
                if (li == null) {
                    continue;
                }
                Elements aList = li.getElementsByTag("a");
                if (CollectionUtil.isEmpty(aList)) {
                    continue;
                }
                Element pElement = li.selectFirst("p");
                if (pElement == null) {
                    continue;
                }
                Elements divBottom = li.getElementsByClass("bottom");
                if (divBottom == null || divBottom.size() != 1) {
                    continue;
                }
                Elements spanList = divBottom.get(0).getElementsByTag("span");
                if (CollectionUtil.isEmpty(spanList) || spanList.size() != 2) {
                    continue;
                }

                Element aElement = aList.get(0);
                String title = aElement.text().trim();
                log.info("获取到文章标题：{}", title);
                String url = aElement.attr("href");
                log.info("获取到文章链接：{}", url);
                // 摘要
                String overview = pElement.text().trim();
                log.info("获取到文章摘要：{}", overview);
                // 发文时间
                String publishTime = spanList.get(0).text().trim();
                log.info("获取到文章发布时间：{}", publishTime);
                // 来源
                String source = spanList.get(1).text().trim();
                log.info("获取到文章来源：{}", source);
                log.info("-------------------------------------------------------------");
                String uuid = UUIDUtil.getUUID();
                Integer count = this.baseMapper.queryCountByTitleAndType(title, policyTypeMap.get(type));
                if(count > 0) {
                    log.info("文章已存在，跳过保存");
                    continue;
                }
                GovArticleBodyAndFileDto article = this.getAndDealHtmlArticle(url);
                if(article != null) {
                    GovArticle govArticle = new GovArticle();
                    govArticle.setBaseId(uuid);
                    govArticle.setLevel("省");
                    govArticle.setPolicyType(policyTypeMap.get(type));
                    govArticle.setTitle(title);
                    govArticle.setOverview(overview);
                    govArticle.setSource("山东省工业和信息化厅");
                    if(publishTime.length() == 16) {
                        publishTime = publishTime + ":00";
                    }
                    govArticle.setArticlePublishTime(DateUtil.parse(publishTime, "yyyy-MM-dd HH:mm:ss"));
                    govArticle.setUrl(url);
                    govArticle.setBody(article.getBody());
                    if(CollectionUtil.isNotEmpty(article.getFileList())) {
                        govArticle.setFileUrl(String.join(",", article.getFileList()));
                    }
                    govArticle.setBaseCreateTime(DateUtil.date());
                    govArticle.setIsDelete(0);
                    govArticle.setArticleType("web");
                    govArticle.setFormId(GxmhConstant.DEFAULT_FORM_ID);
                    this.save(govArticle);
                    Thread.sleep(10000L);
                }
            }catch (Exception e) {
                log.error("解析政策列表页面文章失败：{}", ExceptionUtil.stacktraceToString(e));
            }
        }
    }

    /**
     * 获取html文章内容，去除其他不必要的标签
     * @param url
     * @return
     */
    public GovArticleBodyAndFileDto getAndDealHtmlArticle(String url) {
        try {
            Document documentFromURL = JsoupUtils.getDocumentFromURL(url);
            if (documentFromURL == null) {
                log.error("获取html文档失败：{}", url);
                return null;
            }
            Elements w1200 = documentFromURL.getElementsByClass("w1200");
            if (CollectionUtil.isEmpty(w1200)) {
                log.error("无法解析html文档：{}", url);
                return null;
            }
            Element w1200element = w1200.get(0);
            if(w1200element == null) {
                log.error("无法解析html文档：{}", url);
                return null;
            }

            Element tree = w1200element.getElementById("tree");
            if(tree != null) {
                tree.remove();
            }
            Elements select = w1200element.select("style");
            if(CollectionUtil.isNotEmpty(select)) {
                for(Element styleElement : select) {
                    styleElement.remove();
                }
            }

            Elements scriptList = w1200element.select("script");
            if (CollectionUtil.isNotEmpty(scriptList)) {
                for (int i = 0; i < scriptList.size(); i++) {
                    scriptList.get(i).remove();
                }
            }

            Elements s17= w1200element.getElementsByClass("s17");

            if(CollectionUtil.isEmpty(s17)) {
                log.error("无法解析html文档：{}", url);
                return null;
            }
            Element s17Element = s17.get(0);
            Element child = s17Element.child(0);
            if(child != null) {
                Elements tables = child.select("table");
                if(CollectionUtil.isNotEmpty(tables)) {
                    for(Element tableElement : tables) {
                        tableElement.remove();
                    }
                    child.remove();
                }
            }

            Elements styleList = s17Element.select("style");
            if(CollectionUtil.isNotEmpty(styleList)) {
                for(Element styleElement : styleList) {
                    styleElement.remove();
                }
            }

            Elements floating = s17Element.getElementsByClass("floating");
            if (CollectionUtil.isNotEmpty(floating)) {
                for (Element floatingElement : floating) {
                    floatingElement.remove();
                }
            }
            // 处理附件连接
            List<String> fileList = new ArrayList<>();
            Elements aList = s17Element.select("a");
            if (CollectionUtil.isNotEmpty(aList)) {
                for (Element aElement : aList) {
                    String href = aElement.attr("href");
                    if (StrUtil.isNotEmpty(href) && href.contains("downfile.jsp")) {
                        String fullUrl = "http://gxt.shandong.gov.cn" + href;
                        fileList.add(fullUrl);
                        aElement.remove();
                    }
                }
            }

            // 浏览次数
            Elements headlines = s17Element.getElementsByClass("headline");
            if(CollectionUtil.isNotEmpty(headlines)) {
                Element headlineElement = headlines.get(0);
                Elements labels = headlineElement.select("label");
                if(CollectionUtil.isNotEmpty(labels)) {
                    for(Element labelElement : labels) {
                        if(labelElement.text().contains("浏览次数")) {
                            labelElement.remove();
                        }
                    }
                }
            }

            // 处理图片
            Elements imgList = s17Element.select("img");
            if(CollectionUtil.isNotEmpty(imgList)) {
                for(Element imgElement : imgList) {
                    String src = imgElement.attr("src");
                    if(StrUtil.isNotEmpty(src) && src.startsWith("/picture")) {
                        String fullUrl = "http://gxt.shandong.gov.cn" + src;
                        imgElement.attr("src", fullUrl);
                    }
                    String style = imgElement.attr("style");
                    if(StrUtil.isNotEmpty(style)) {
                        style = style + "width:100%;";
                        imgElement.attr("style", style);
                    }else {
                        imgElement.attr("style", "border:none;width:100%;");
                    }
                }
            }

            // 处理视频
            Elements videoList = s17Element.select("video");
            if(CollectionUtil.isNotEmpty(videoList)) {
                for(Element videoElement : videoList) {
                    String src = videoElement.attr("src");
                    if(StrUtil.isNotEmpty(src) && src.startsWith("/media")) {
                        String fullUrl = "http://gxt.shandong.gov.cn" + src;
                        videoElement.attr("src", fullUrl);
                    }
                }
            }

            String html = w1200.html().replace("\n", "");
            GovArticleBodyAndFileDto dto = new GovArticleBodyAndFileDto();
            dto.setBody(html);
            dto.setFileList(fileList);
            return dto;
        }catch (Exception e) {
            log.error("处理html文档失败：{}", ExceptionUtil.stacktraceToString(e));
            return null;
        }
    }

    public boolean saveArticle(String uuid, String url) {
        try {
            Document documentFromURL = JsoupUtils.getDocumentFromURL(url);
            if (documentFromURL == null) {
                log.error("获取html文档失败：{}", url);
                return false;
            }
            Elements w1200 = documentFromURL.getElementsByClass("w1200");
            if (CollectionUtil.isEmpty(w1200)) {
                log.error("无法解析html文档：{}", url);
                return false;
            }
            Element w1200Element = w1200.get(0);
            Element tree = w1200Element.getElementById("tree");
            if (tree != null) {
                tree.remove();
            }
//        Elements styleList = w1200Element.select("style");
//        if(CollectionUtil.isNotEmpty(styleList)) {
//            for(Element styleElement : styleList) {
//                styleElement.remove();
//            }
//        }
            Elements scriptList = w1200Element.select("script");
            if (CollectionUtil.isNotEmpty(scriptList)) {
                for (int i = 0; i < scriptList.size(); i++) {
                    if (i != scriptList.size() - 1) {
                        // 最后一个脚本会设置文章开头的表格，保留
                        scriptList.get(i).remove();
                    }
                }
            }
            Elements floating = w1200Element.getElementsByClass("floating");
            if (CollectionUtil.isNotEmpty(floating)) {
                for (Element floatingElement : floating) {
                    floatingElement.remove();
                }
            }
            // 处理附件连接
            Elements aList = w1200Element.select("a");
            if (CollectionUtil.isNotEmpty(aList)) {
                for (Element aElement : aList) {
                    String href = aElement.attr("href");
                    if (StrUtil.isNotEmpty(href) && href.contains("downfile.jsp")) {
                        String fullUrl = "http://gxt.shandong.gov.cn" + href;
                        aElement.attr("href", fullUrl);
                    }
                }
            }
            String html = buildHtml(w1200Element.html());
            return JsoupUtils.saveHtml(html, Paths.get(GOV_FILE_PATH + uuid + ".html"));
        }catch (Exception e) {
            log.error("保存html文档失败：{}", ExceptionUtil.stacktraceToString(e));
            return false;
        }
    }

    private boolean downFile(String fileUrl, String fileName) {
        URL url = null;
        InputStream inputStream = null;
        try {
            url = new URL(fileUrl);
            inputStream = url.openStream();
            Files.copy(inputStream, Paths.get(GOV_FILE_ATTACHMENT_PATH + fileName), StandardCopyOption.REPLACE_EXISTING);
            return true;
        }catch (Exception e) {
            log.error("文件下载失败， URL：{}, 异常：{}", fileUrl, ExceptionUtil.stacktraceToString(e));
            return false;
        }finally {
            if(inputStream != null){
                IOUtils.closeQuietly(inputStream);
            }
        }
    }

    private String buildHtml(String bodyContent) {
        StringBuilder sb = new StringBuilder();
        sb.append("<!DOCTYPE html>")
                .append("<html>")
                .append("<head>");
        sb.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
        sb.append("<link href=\"./css/infotag.css\" type=\"text/css\" rel=\"stylesheet\">");
        sb.append("<link href=\"./css/common.css\" type=\"text/css\" rel=\"stylesheet\">");
        sb.append("<link href=\"./css/globle.css\" type=\"text/css\" rel=\"stylesheet\">");
        sb.append("<link href=\"./css/second.css\" type=\"text/css\" rel=\"stylesheet\">");
        sb.append("<script type=\"text/javascript\" src=\"./js/jquery.js\"></script>");
        sb.append("</head>");
        sb.append("<body>").append(bodyContent).append("</body>").append("</html>");
        return sb.toString();
    }

    private String getGovListUrl(String type, String pageNum) {
        if("规范性文件".equals(type)) {
            return String.format(GOV_LIST_URL, "col103862", "SD020203", "641892", pageNum);
        }
        if("其他文件".equals(type)) {
            return String.format(GOV_LIST_URL, "col103863", "SD020206", "641892", pageNum);
        }
        if("规范性文件清理".equals(type)) {
            return String.format(GOV_LIST_URL, "col103864", "SD020205", "", "");
        }
        if("政策解读".equals(type)) {
            return String.format(GOV_LIST_URL, "col103865", "SD020207", "641892", pageNum);
        }
        throw new BusinessException("未知文件类型");
    }

}
